<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app" class="app">
    <ul id="li_box">
        <li>[].slice.call()</li>
        <li>Object.keys</li>
        <li>Object.defineProperty</li>
<!--        <li>node.nodeType</li> 请不要删除此注释,否则代码不会执行-->
        <li>DocumentFragment(虚拟DOM)</li>
    </ul>
<!--    <div id="li_box">div的内容</div>-->
</div>
<script>
//1.[].slice.call() 类数组(伪数组)转换成数组
let lis = document.getElementsByTagName("li");
// let arr = [].slice.call(lis);
// let arr = Array.prototype.slice.call(lis);
// Array.form()
console.log(lis);

//2.Object上常用的API都有那些  keys defineProperty hasOwnProperty assign
// let obj = {};
// let obj2 = {name:1};
// Object.assign(obj,obj2)

//3.Object.defineProperty() 方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性，并返回此对象。
//语法
/**
 * Object.defineProperty 定义属性
 * obj: 要增加或者修改属性的对象
 * prop: 属性名
 * descriptor: 属性描述符
 *  configurable: 布尔值 --> 是否可重新配置(删除) 默认为 false。
 *  enumerable: 布尔值 --> 是否可枚举 默认为 false。
 *  //数据描述符
 *  value: 默认值
 *  writable: 布尔值 --> 是否可重写 默认为 false
 *  //存取(访问)描述符
 *  get(): 回调函数 当此属性被读取的时候会触发这个回调函数(这个属性可以根据其他属性,动态计算当前属性的值)
 *  set(): 回调函数 当前属性值发生改变之后会触发这个回调函数
 *
 * 数据描述符和访问描述符不能同时存在
 *
 * return 修改后的对象(obj)
 */
// Object.defineProperty(obj, prop, descriptor)
//
let obj = {
    firstName: "A",
    lastName: "B",
}
Object.defineProperty(obj, "fullName", {
    configurable:true,
    enumerable: true,
    get(){
        console.log("get方法被触发")
        return this.firstName + "-" + this.lastName
    },
    set(newValue){
        console.log("set方法被触发",newValue);//"C-D"
        let fullNameArr = newValue.split("-");
        this.firstName = fullNameArr[0];
        this.lastName = fullNameArr[1];
    }
});

Object.defineProperty(obj, "fullName1", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: "哈哈"
});


/*//删除属性
delete obj.fullName*/

//Cannot redefine property: fullName  configurable默认不可重新配置
/*Object.defineProperty(obj, "fullName", {
    get(){
        console.log("get方法被触发111")
        return this.firstName + "-" + this.lastName
    },
    set(newValue){
        console.log("set方法被触发22",newValue);//"C-D"
        let fullNameArr = newValue.split("-");
        this.firstName = fullNameArr[0];
        this.lastName = fullNameArr[1];
    }
});*/
/*obj.firstName = "C"
console.log(obj.fullName);//"C-B"
obj.fullName = "E-F";
console.log(obj.firstName);//"E
console.log(obj.lastName);//"F*/

//面试题  vue2.0+为什么不兼容IE8?
// vue2.0中核心代码的核心语句就是Object.defineProperty方法, 这个方法是ES6语法, 而IE8不支持ES6语法 所以vue2.0不支持IE8浏览器

//vue3.0 核心双向数据绑定语法  Object.proxy()


//node.nodeType

//node节点
// 文档节点 document->(html)
// 元素节点 element->标签 1
// 属性节点 attribute 2
// 文本节点 text 3
// 注释节点 comm 8

/*let ul = document.getElementById("li_box");
let attrNode = ul.getAttributeNode("id");
let textNode = ul.firstChild;

console.log(ul.nodeType,attrNode.nodeType,textNode.nodeType)//1 2 3*/

/*let ul = document.getElementById("li_box");
let childNodes = ul.childNodes;
if(childNodes[8].nodeType !== 8){
    throw new Error("ssssss")
}*/

/*<div id="div1" class="div2">hello word</div>*/
/*let vnode = {
    id: 1,
    arrt:{
        id:"div1",
        class:"div2"
    },
    nodeType:1,
    tag: "div"
}*/


/*
*     <ul id="li_box"></ul>
* */
//DocumentFragment文档碎片
//DocumentFragment，文档片段接口，一个没有父对象的最小文档对象。它被作为一个轻量版的 Document 使用，就像标准的document一样，存储由节点（nodes）组成的文档结构。与document相比，最大的区别是DocumentFragment 不是真实 DOM 树的一部分，它的变化不会触发 DOM 树的重新渲染，且不会导致性能等问题。
//Document => body => 一旦节点发生改变, 那么一定会触发dom树重新渲染
//DocumentFragment => 轻量版的 Document => 内存 =>节点发生改变, dom树并不会触发任何的改变


/*let ul = document.getElementById("li_box");
console.dir(ul)
Array.from(ul.children).forEach((li)=>{
    // debugger;
    // li.textContent = "你好世界"
    li.innerText = "你好世界"
})*/
let ul = document.getElementById("li_box");

//1.创建DocumentFragment
let docFragment = document.createDocumentFragment();

//2.将所有子节点放入DocumentFragment中
Array.from(ul.childNodes).forEach((item)=>{
    let cloneNode = item.cloneNode()
    docFragment.appendChild(cloneNode)
})

//3.更新DocumentFragment中所有的li中的内容
Array.from(docFragment.childNodes).forEach((item)=>{
    if(item.nodeType === 1){
        item.textContent = "你好世界"
    }
})

debugger;
//4.把DocumentFragment更新到页面
ul.innerHTML = "";

debugger;
ul.appendChild(docFragment)



</script>
</body>
</html>